import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Locale;
import java.util.Scanner;

/*
 * Structure
 * Name GAO RISHENG
 */

public class CommandDecoder {
	private static final int INDEX_START = 0;
	private static final int INDEX_TYPE = 0;
	private static final int INDEX_TITLE = 1;
	private static final int INDEX_TIME = 2;
	private static final int INDEX_TAG = 3;
	private static final int INDEX_URGENCY = 4;
	private static final String DEFAULT_URGENCY_LEVEL = "8";
	private static String[][]         commandKeyWords = {{"exit","quit","out","leave"},
		{"add","+","plus"},
		{"delete","del","minus","-","remove","forget","ignore"},
		{"edit","modify","change"},
		{"clear","clean"},
		{"sort","rearrange","order"},
		{"search","find","list","catch","get","retrive"},
		{"finish","complete","kill","mark"},
		{"display","show","achievement"},
		{"undo"}};
	private enum COMMAND_TYPE {
		EXIT,
		ADD,
		REMOVE,
		MODIFY,
		CLEAR,
		SORT,
		SEARCH,
		FINISH,
		DISPLAY,
		UNDO,
		INVALID_COMMAND;
	};
	private ArrayList<String> contents = new ArrayList<String>();
	private FileManager fileManager= new FileManager();
	private String  rawInput=new String();
	private static ArrayList<Command> history = new ArrayList<Command>();
	private static ArrayList<Task> virtualStorage = new ArrayList<Task>();
	public CommandDecoder(String userInput) {
		rawInput=userInput;
	}
	public CommandDecoder() {
	}
	public String getRawInput() {
		return rawInput;
	}

	public ArrayList<String> decodeTheContent(String userInput) {
		contents.add(decodeTheCommandType(userInput).toString());
		decodeTheOperation(decodeTheCommandType(userInput));
		return contents;
	}
	private String getCommandType(String rawInput) {
		String[] commandLine = rawInput.split(" ");
		String rawCommandType = commandLine[INDEX_START];
		return rawCommandType;
	}
	private COMMAND_TYPE decodeTheCommandType(String userInput) {
		String rawInputType = this.getCommandType(userInput);
		COMMAND_TYPE inputType = this.decodeRawCommandType(rawInputType);
		return inputType;
	}
	public void decodeTheOperation(COMMAND_TYPE commandType) {
		switch (commandType) {
		case EXIT: {
			break;
		}
		case ADD: {
			decodeTheContentsForAddCommand();
			break;
		}
		case REMOVE: {
			decodeTheContentsForRemoveCommand();
			break;
		}
		case MODIFY: {
			decodeTheContentsForModifyCommand();
		}		
		case SORT : {
			decodeTheContentForSortCommand();
			break;
		}
		case SEARCH : {
			decodeTheContentForSearchCommand();
			break;
		}
		case FINISH : {
			decodeTheContentForFinishCommand();
			break;
		}
		case CLEAR:
		case DISPLAY :
		case UNDO :
		case INVALID_COMMAND : {
			break;
		}
		}
	}
	
	private static COMMAND_TYPE decodeRawCommandType(String rawCommandType) {
		for(int commandType = INDEX_START;commandType<commandKeyWords.length;commandType++) {
			for(int keywordIndex = INDEX_START;keywordIndex<commandKeyWords[commandType].length;keywordIndex++) {
				if(rawCommandType.toLowerCase().equals(commandKeyWords[commandType][keywordIndex])) {
					return COMMAND_TYPE.values()[commandType];
				}
			}
		}
		return COMMAND_TYPE.INVALID_COMMAND;
	}
	
	private static String removeHeader(String input, String separator) {
		if(input.contains(separator))
		return input.substring(input.indexOf(separator)+separator.length());
		else 
		return "";
	}

	
	//for ADD operation
	private void decodeTheContentsForAddCommand() {
		//contents.add("ADD");
		String taskContent = separateTheContent(rawInput," ");
		String taskTitle = retriveHeader(taskContent," @ ");
		contents.add(taskTitle);
		taskContent = separateTheContent(taskContent," @ ");
		String taskTime = decodeTheTime(retriveHeader(taskContent," # "));
		contents.add(taskTime);
		taskContent = separateTheContent(taskContent," # ");
		String taskTag = retriveHeader(taskContent," % ");
		if(isThisNull(taskTag)) {
			contents.add("Null Tag");
		}
		else {
			contents.add(taskTag);
		}
		String taskLevel = separateTheContent(taskContent," % ");
		if(taskLevel.equals(taskContent)) {
			contents.add(DEFAULT_URGENCY_LEVEL);
		} else {
			contents.add(taskLevel);
		}		
	}
	private String separateTheContent(String input, String separator) {
		if(input.contains(separator)) {
			return input.substring(input.indexOf(separator)+separator.length()).trim();
		}
		return input;
	}
	private String retriveHeader(String input,String separator) {
		if(input.contains(separator)) {
		String buffer[] = input.split(separator);
		return buffer[INDEX_START].trim();
		}
		else return "";
	}
	private boolean isThisNull(String input) {
		return input.equals(null);
	}
	private static String decodeTheTime(String time) {
		try {
			Date theDate = new SimpleDateFormat("MMMM dd yyyy HH:mm", Locale.ENGLISH).parse(time);
			SimpleDateFormat standardFormat = new SimpleDateFormat("MMMM dd yyyy HH:mm",Locale.ENGLISH);
			return standardFormat.format(theDate);
		} catch(Exception e) {
			try {
				Date theDate = new SimpleDateFormat("MMMM dd yyyy", Locale.ENGLISH).parse(time);
				SimpleDateFormat standardFormat = new SimpleDateFormat("MMMM dd yyyy HH:mm",Locale.ENGLISH);
				return standardFormat.format(theDate);
			} catch (Exception error) {
				try {
					Date theDate = new SimpleDateFormat("MM/dd/yyyy HH:mm", Locale.ENGLISH).parse(time);
					SimpleDateFormat standardFormat = new SimpleDateFormat("MMMM dd yyyy HH:mm",Locale.ENGLISH);
					return standardFormat.format(theDate);
				} catch (Exception timeError) {
					timeError.printStackTrace();
				}
			}
		}
		return "";
	}
	
	//REMOVE operation
	private void decodeTheContentsForRemoveCommand() {
		String buffer[] = rawInput.split(" ");
	// reserve for future develop
	//	for(int index = 1; index<buffer.length; index ++ ) {
	//		contents.add(buffer[index]);
	//	}
		if(buffer.length>1)
		contents.add(buffer[1]);
	}

	//MODIFY operation
	private void decodeTheContentsForModifyCommand() {
		
		contents = decodeTheModifyCommand(rawInput);
	}
	private ArrayList<String> decodeTheModifyCommand(String rawInput) {
		ArrayList<String> contents = new ArrayList<String> ();
		String type = retriveHeader(rawInput," ");
		contents.add(decodeRawCommandType(type).toString());
		String content = removeHeader(rawInput,type);
		content = content.trim();
		String pureContent[] = content.split(" AS ");
		String originalContent[] = pureContent[INDEX_START].split("/");
		String editedContent[] = pureContent[pureContent.length-1].split("/");
		for(int INDEX = INDEX_START;INDEX<originalContent.length;INDEX++) {
			System.out.println(originalContent[INDEX]);
			contents.add(originalContent[INDEX]);
		}
		contents.add("/");
		for(int INDEX = INDEX_START;INDEX<editedContent.length;INDEX++) {
			System.out.println(editedContent[INDEX]);
			contents.add(editedContent[INDEX]);
		}
		return contents;
		
	}
	//SORT opeartion
	private void decodeTheContentForSortCommand() {
		String buffer[] = rawInput.split(" ");
		// reserve for future develop
		//	for(int index = 1; index<buffer.length; index ++ ) {
		//		contents.add(buffer[index]);
		//	}
		if(buffer.length>1)
			contents.add(buffer[1]);	
	}

	//SEARCH opeartion
	private void decodeTheContentForSearchCommand() {
		
		contents= separateKeyWordContent(rawInput);
	}
	private ArrayList<String> separateKeyWordContent(String rawInput) {
		String type=retriveHeader(rawInput," ");
		String rawContent = separateTheContent(rawInput," ");
		rawContent =  rawContent.trim();
		String keyWords[] = rawContent.split("/");
		ArrayList<String> Contents = new ArrayList<String>();
		Contents.add(decodeRawCommandType(type).toString());
		for(int INDEX=INDEX_START;INDEX<keyWords.length;INDEX++) {
			Contents.add(keyWords[INDEX]);
		}
		return Contents;
	}
	//FINISH opeartion
	private void decodeTheContentForFinishCommand() {
		String buffer[] = rawInput.split(" ");
		
		if(buffer.length>1) {
			String bufferContent[] = buffer[1].split("/");
			for(int index = INDEX_START;index<bufferContent.length;index++) {
				contents.add(bufferContent[index]);
			}
		}
		
	}
}
